package com.edu.admin.service;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.edu.admin.common.BaseService;
import com.edu.admin.entity.SysAdmin;
import com.edu.admin.entity.SysSchool;
import com.edu.admin.enums.ExceptionEnum;
import com.edu.admin.enums.UseTypeEnum;
import com.edu.admin.exception.SysException;
import com.edu.admin.mapper.AdminMapper;
import com.edu.admin.mapper.SchoolMapper;
import com.edu.admin.utils.DateUtils;
import com.edu.admin.utils.TokenUtils;
import com.edu.admin.vo.AdminVo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

/**
 * 管理员服务
 *
 * @author Wangjiong
 * 
 */
@Transactional
@Service
public class AdminService extends BaseService<AdminMapper, SysAdmin>{
	@Autowired
	AuthenticationManager authenticationManager;
	@Autowired
	SchoolMapper schoolMapper;
	@Autowired
	TokenUtils tokenUtil;
	
	/**
	 * 获取管理员信息
	 * 
	 * @param adminId
	 * 
	 * @return SysAdmin
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 */
	public SysAdmin getAdmin(Long adminId) throws IllegalAccessException, InvocationTargetException{
		
		SysAdmin admin = this.mapper.findAdminByAdminId(adminId);
		
		return admin;
	}
	
	/**
     * 管理员登录
     * 
     * @param username
     * @param password
     * 
     * @return SysAdmin
     * @throws Exception
     */
    public SysAdmin loginAdmin(String username,String password) throws Exception {
    	
    	SysAdmin admin = this.mapper.findAdminByUsername(username);
        
        if(admin == null){
        	throw new SysException(ExceptionEnum.AUTHERROR);
        }else{
        	
        	if (admin.getUseType()!=0)
        	{
        		throw new SysException(ExceptionEnum.USERDISABLE);
        	}
        	
            SysSchool school = schoolMapper.selectByPrimaryKey(admin.getSchoolId());
            if(school != null && school.getUseType() != 0){
            	throw new SysException(ExceptionEnum.SCHOOLDISABLE);
            }
            
            List<String> menuList = getAllMenuList(admin.getAdminId());
            if (menuList!=null && menuList.size()>0)
            {
            	admin.setFirstMenuUrl(menuList.get(0));
            }
            else
            {
            	throw new SysException(ExceptionEnum.NOAUTHORITY);
            }
           
            //用户验证
            final Authentication authentication = authenticate(username, password);
            //存储认证信息
            SecurityContextHolder.getContext().setAuthentication(authentication);
            //生成token
            SysAdmin tokenAdmin = (SysAdmin) authentication.getPrincipal();
            
            final String token = tokenUtil.generateAccessToken(tokenAdmin);
            //存储token
            tokenUtil.putToken(username, token);
            
            admin.setLoginDate(DateUtils.getNowTime());
            
            updateByPrimaryKeySelective(admin);
            
            admin.setToken(token);
            
     		return admin;
        }
    }
    
    /**
     * 管理员注销
     * 
     * @param token
     * 
     * @return 
     */
    public void logoutAdmin(String token) {
        String userName = tokenUtil.getUsernameFromToken(token);
        if (userName!=null)
        {
        	tokenUtil.deleteToken(userName);
        }
    }
    
    /**
	 * 获取管理员列表
	 * 
	 * @param String schoolName
	 * @param String adminName
	 * @param String account
	 * @param String roleId
	 * 
	 * @return List<AdminVo>
	 */
    public List<AdminVo> getAdminList(String schoolName, String adminName,String account,Long roleId) {
		
		List<AdminVo> adminList = this.mapper.getAdminList(schoolName, adminName, account, roleId);
		
		return adminList;
	}
	
	
	/**
	 * 获取所有管理员列表（包括停用管理员）
	 * 
	 * @param Integer pageNum
	 * @param Integer pageSize
	 * @param String schoolName
	 * @param String adminName
	 * @param String account
	 * @param String roleId
	 * 
	 * @return PageInfo<AdminVo>
	 */
	public PageInfo<AdminVo> getAllAdminListPage(Integer pageNum, Integer pageSize,
					String schoolName, String adminName,String account,Long roleId) {
		if (pageNum == null) {
			pageNum = 1;
		}
		if (pageSize == null) {
			pageSize = 10;
		}
		PageHelper.startPage(pageNum, pageSize);
		
		List<AdminVo> adminList = this.mapper.getAllAdminList(schoolName, adminName, account, roleId);
		
		PageInfo<AdminVo> pageInfo = new PageInfo<AdminVo>(adminList);

		return pageInfo;
	}
	
	
	/**
	 * 获取所有管理员列表（包括停用管理员）
	 * 
	 * @param String schoolName
	 * @param String adminName
	 * @param String account
	 * @param String roleId
	 * 
	 * @return List<AdminVo>
	 */
	public List<AdminVo> getAllAdminList(String schoolName, String adminName,String account,Long roleId) {
			
		List<AdminVo> adminList = this.mapper.getAllAdminList(schoolName, adminName, account, roleId);
		
		return adminList;
	}
	
    /**
     * 管理员排重
     * 
     * @param SysAdmin admin
     * 
     * @return List<AdminVo>
     * @throws Exception
     */
    public List<AdminVo> checkAdmin(SysAdmin admin) throws Exception {
    	
    	return this.mapper.findAdminByAccount(admin.getAdminId(),admin.getAccount());
  
    }
	
	/**
	 * 管理员保存
	 * 
	 * @param admin
	 * 
	 * @return Map<String, Object>
	 */
	public Map<String, Object> saveAdmin(SysAdmin admin) throws Exception {
		Map<String, Object> result = new HashMap<>();
		
		admin.setAccount(admin.getPhone().trim());
		
		List<AdminVo> adminList = checkAdmin(admin);
		
		if (adminList!=null && adminList.size()>0)
		{
			throw new SysException(ExceptionEnum.ADMINPHONEREPEAT);
		}
		
		if(admin.getUseType()==null)
		{
			admin.setUseType(UseTypeEnum.ISUSE.getCode());
		}
		
		Long adminId = admin.getAdminId();

		if (adminId == null) {
			
			if (admin.getPassword()==null)
			{
				BCryptPasswordEncoder  passwordEncoder = new BCryptPasswordEncoder();
		        admin.setPassword(passwordEncoder.encode("123456"));
			}
			
			insert(admin);
			
			adminId = admin.getAdminId();
		

		} else {
			
			if(admin.getRoleLevel().equals("1"))
			{
				admin.setSchoolId(new Long(0));
			}
			
			updateByPrimaryKeySelective(admin);

		}
		
		result.put("adminId", adminId);

		return result;
		

	}

	
	/**
	 * 管理员密码重置保存
	 * 
	 * @param adminId
	 * 
	 * @return int
	 */
	public int resetAdminPassword(Long adminId) {
		
		if (adminId != null) {
			SysAdmin admin = new SysAdmin();
			admin.setAdminId(adminId);
			BCryptPasswordEncoder  passwordEncoder = new BCryptPasswordEncoder();
	        admin.setPassword(passwordEncoder.encode("123456"));
			return updateByPrimaryKeySelective(admin);

		}
		
		return 0;
		

	}
	
	
	/**
	 * 删除管理员
	 * 
	 * @param adminId
	 * 
	 * @return int
	 */
	public int deleteAdmin(Long adminId) {
		
		if (adminId != null) {
			return this.deleteByPrimaryKey(adminId);

		}
		
		return 0;	

	}
	
	/**
	 * 启用停用管理员
	 * 
	 * @param adminId
	 * @param useType
	 * 
	 * @return int
	 */
	public int useAdmin(Long adminId,Integer useType) {
		
		if (adminId != null) {
			SysAdmin admin = new SysAdmin();
			admin.setAdminId(adminId);
	        admin.setUseType(useType);
			return updateByPrimaryKeySelective(admin);

		}
		
		return 0;	

	}
	
	/**
	 * 获取管理员菜单列表
	 * 
	 * @param adminId
	 * 
	 * @return List<String>
	 */
    public List<String> getMenuList(Long adminId) {
		
		List<String> menuList = this.mapper.getMenuList(adminId);
		
		return menuList;
	}
    
    /**
	 * 获取管理员菜单列表（包含父菜单）
	 * 
	 * @param adminId
	 * 
	 * @return List<String>
	 */
    public List<String> getAllMenuList(Long adminId) {
		
		List<String> menuList = this.mapper.getAllMenuList(adminId);
		
		return menuList;
	}
    
    /**
	 * 管理员密码修改
	 * 
	 * @param adminId
	 * 
	 * @return int
     * @throws Exception 
	 */
	public int updatePassword(Long adminId,String oldPassword, String newPassword) throws Exception {
		
		if (adminId != null) {
			SysAdmin admin = getAdmin(adminId);
			
			String pwd = admin.getPassword();
			
			BCryptPasswordEncoder  passwordEncoder = new BCryptPasswordEncoder();
			
			boolean isCorrect = passwordEncoder.matches(oldPassword,pwd);
			
			if(!isCorrect){ 
				throw new SysException(ExceptionEnum.OLDPASSWORDERROR);
			}
			 
			if (newPassword!=null)
			{
				admin.setPassword(passwordEncoder.encode(newPassword));
			}
						
			return updateByPrimaryKeySelective(admin);

		}
		
		return 0;
		

	}
	
	private Authentication authenticate(String username, String password) {
        try {
            //该方法会去调用userDetailsService.loadUserByUsername()去验证用户名和密码，如果正确，则存储该用户名密码到“security 的 context中”
            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
        } catch (DisabledException | BadCredentialsException e) {
            throw new SysException(ExceptionEnum.AUTHERROR);
        }
    }

}
